package v1

import (
	"ginblog/middleware"
	"ginblog/model"
	"ginblog/utils/errmsg"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/golang-jwt/jwt/v5"
)

// Login 后台登陆
// Login handles the user login logic.
// It receives a gin.Context as a parameter, which contains the request and response context.
func Login(c *gin.Context) {
	// Initialize a User object to store the submitted form data.
	var formData model.User

	// Attempt to bind the request's JSON data to the formData object. Any errors are ignored.
	_ = c.ShouldBindJSON(&formData)

	// Declare a token variable and a status code variable.
	var token string
	var code int

	// Call the CheckLogin function to verify the username and password, and obtain the processing results including the updated form data and status code.
	formData, code = model.CheckLogin(formData.Username, formData.Password)

	// If the login is successful, set the token.
	if code == errmsg.SUCCESS {
		setToken(c, formData)
	} else {
		// If the login fails, return the error information and the empty token.
		c.JSON(http.StatusOK, gin.H{
			"status":  code,
			"data":    formData.Username,
			"id":      formData.ID,
			"message": errmsg.GetErrMsg(code),
			"token":   token,
		})
	}
}

// LoginFront 前台登录
// LoginFront 用户前端登录函数
// 参数: c *gin.Context 上下文，用于处理HTTP请求和响应
// 该函数处理前端用户的登录请求，验证用户提供的用户名和密码
func LoginFront(c *gin.Context) {
	// 初始化一个User结构体用于绑定请求的表单数据
	var formData model.User

	// 尝试从请求中解析JSON数据并绑定到formData变量中
	// 注意：这里忽略了错误处理，实际应用中应该适当处理解析错误
	_ = c.ShouldBindJSON(&formData)

	// 定义一个变量用于存储登录验证后的状态码
	var code int

	// 调用CheckLoginFront函数验证用户名和密码，并获取验证后的用户信息和状态码
	formData, code = model.CheckLoginFront(formData.Username, formData.Password)

	// 构建并发送JSON响应，包含登录状态码、用户名、用户ID和对应的消息
	c.JSON(http.StatusOK, gin.H{
		"status":  code,                   // 登录状态码
		"data":    formData.Username,      // 登录成功的用户名
		"id":      formData.ID,            // 登录成功的用户ID
		"message": errmsg.GetErrMsg(code), // 根据状态码获取对应的消息
	})
}

// token生成函数
// setToken 为用户生成JWT令牌并返回给客户端。
// 该函数接收一个gin的上下文和一个用户模型作为参数。
// 它使用中间件中的NewJWT方法实例化一个新的JWT对象，并为用户生成一个包含用户名和有效期等信息的令牌。
// 如果令牌生成失败，它会返回一个错误信息和状态码；如果成功，它会将令牌和用户信息返回给客户端。
func setToken(c *gin.Context, user model.User) {
	// 实例化一个新的JWT对象。
	j := middleware.NewJWT()

	// 创建一个自定义的JWT claims，包含用户用户名、令牌生效和过期时间、以及发行者信息。
	claims := middleware.MyClaims{
		Username: user.Username,
		RegisteredClaims: jwt.RegisteredClaims{
			NotBefore: jwt.NewNumericDate(time.Now()),
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(7 * 24 * time.Hour)),
			Issuer:    "GinBlog",
		},
	}

	// 使用JWT对象和自定义claims生成JWT令牌。
	token, err := j.CreateToken(claims)

	// 如果生成令牌过程中出现错误，返回错误信息和状态码。
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"status":  errmsg.ERROR,
			"message": errmsg.GetErrMsg(errmsg.ERROR),
			"token":   token,
		})
		return
	}

	// 如果令牌生成成功，返回用户信息、状态码和JWT令牌。
	c.JSON(http.StatusOK, gin.H{
		"status":  200,
		"data":    user.Username,
		"id":      user.ID,
		"message": errmsg.GetErrMsg(200),
		"token":   token,
	})
}
